
package xj.app;

import java.awt.Frame;
import java.util.ArrayList;
import java.util.List;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;

// singleton

public class LookAndFeelManager { 

  // L&F class names
  static final String metal = "javax.swing.plaf.metal.MetalLookAndFeel";
  static final String motif = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
  static final String nimbus = "sun.swing.plaf.nimbus.NimbusLookAndFeel";

  static final String windows = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  static final String gtk = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
  static final String mac = "com.sun.java.swing.plaf.mac.MacLookAndFeel";

  // jgoodies 
  static final String jgoodies = "com.jgoodies.looks.windows.WindowsLookAndFeel";
  static final String plastic = "com.jgoodies.looks.plastic.PlasticLookAndFeel";
  static final String plastic3D = "com.jgoodies.looks.plastic.Plastic3DLookAndFeel";
  static final String plasticXP = "com.jgoodies.looks.plastic.PlasticXPLookAndFeel";

  static final String substanceCreme = "org.jvnet.substance.skin.SubstanceCremeLookAndFeel";
  static final String substanceCremeCoffee = "org.jvnet.substance.skin.SubstanceCremeCoffeeLookAndFeel";
  static final String substanceSahara = "org.jvnet.substance.skin.SubstanceSaharaLookAndFeel";

  // Look & Feel 
  static final LookAndFeel metalLnF = new LookAndFeel("Metal", metal);
  static final LookAndFeel motifLnF = new LookAndFeel("Motif", motif);
  static final LookAndFeel nimbusLnF = new LookAndFeel("Nimbus", nimbus);

  static final LookAndFeel windowsLnF = new LookAndFeel("Windows", windows);
  static final LookAndFeel gtkLnF = new LookAndFeel("GTK", gtk);
  static final LookAndFeel macLnF = new LookAndFeel("Mac", mac);
  
  static final LookAndFeel plasticLnF = new LookAndFeel("Plastic", plastic);

  static final LookAndFeel substanceLnF = new SubstanceLookAndFeel();
  static final LookAndFeel substanceCremeCoffeeLnF = 
    new SubstanceLookAndFeel("SubstanceCremeCoffee", substanceCremeCoffee);
  static final LookAndFeel substanceSaharaLnF = 
    new SubstanceLookAndFeel("SubstanceSahara", substanceSahara);

  public static LookAndFeelManager getInstance() { 
    if (instance == null) { 
      instance = new LookAndFeelManager();       
    }
    return instance; 
  }

  public LookAndFeel getDefaultLookAndFeel() { 
    if (isMac) return macLnF;
    if (isWindows) return substanceLnF; 
    if (isLinux) return substanceLnF; 
    return metalLnF; 
  }

  public void setDefaultLookAndFeel() { 
    setLookAndFeel(getDefaultLookAndFeel());
  }

  public void setCurrentLookAndFeel(LookAndFeel currentLookAndFeel) { 
    this.currentLookAndFeel = currentLookAndFeel;
  }

  public LookAndFeel getCurrentLookAndFeel() { 
    return currentLookAndFeel;
  }

  public void setLookAndFeel() { 
    setLookAndFeel(currentLookAndFeel);
  }

  public void setLookAndFeel(LookAndFeel lnf) { 
    if (lnf != null) { 
      if (currentLookAndFeel != null) {
	currentLookAndFeel.unsetLookAndFeel();
      }
      currentLookAndFeel = lnf; 
      if (currentLookAndFeel != null) {
	currentLookAndFeel.setLookAndFeel();
      }
    }
  }

  public LookAndFeel findLookAndFeel(String name) { 
    if (name != null) { 
      int n = availableLookAndFeel.size(); 
      for (int i = 0; i < n; i++) { 
	LookAndFeel lnf = availableLookAndFeel.get(i);
	if (name.equals(lnf.getDisplayName())) { 
	  return lnf; 
	}
      }
    }
    return null;
  }

  public List<LookAndFeel> getAvailableLookAndFeel() { 
    return availableLookAndFeel;
  }

  public boolean isWindowsOS() { 
    return isWindows;
  }

  public boolean isLinuxOS() { 
    return isLinux;
  }

  public boolean isMacOS() { 
    return isMac;
  }

  public boolean isDefaultLnF() { 
    LookAndFeel lnf = getDefaultLookAndFeel(); 
    return (currentLookAndFeel == lnf); 
  }

  public boolean isSubstanceLnF() { 
    return (currentLookAndFeel == substanceLnF ||
	    currentLookAndFeel == substanceCremeCoffeeLnF ||
	    currentLookAndFeel == substanceSaharaLnF);
  }

  public boolean isPlasticLnF() { 
    return (currentLookAndFeel == plasticLnF);
  }

  String osname; 
  boolean isWindows = false;
  boolean isMac = false;
  boolean isLinux = false; 

  LookAndFeel currentLookAndFeel; 

  List<LookAndFeel> availableLookAndFeel = new ArrayList<LookAndFeel>();

  private LookAndFeelManager() {    
    String osname = System.getProperty("os.name").toLowerCase();
    init(osname);
  }

  private void init(String osname) {    
    this.osname = osname; 
    if (osname.indexOf("linux") != -1) {
      isLinux = true; 
    } else if (osname.indexOf("windows") != -1) {
      isWindows = true;;
    } else if (osname.indexOf("mac") != -1) {
      isMac = true; 
    }

    availableLookAndFeel.add(metalLnF);
    availableLookAndFeel.add(motifLnF);
    availableLookAndFeel.add(nimbusLnF);
    availableLookAndFeel.add(plasticLnF);
    availableLookAndFeel.add(substanceLnF);
    availableLookAndFeel.add(substanceCremeCoffeeLnF);
    availableLookAndFeel.add(substanceSaharaLnF);
 
    if (isLinux) { 
      availableLookAndFeel.add(gtkLnF);
    }
  }

  private static LookAndFeelManager instance = null; 

  public static class LookAndFeel { 
    public LookAndFeel(String displayName, String className) { 
      this.displayName = displayName;
      this.className =  className;
    }
    
    public String getDisplayName() { 
      return displayName; 
    }

    String displayName; 
    String className; 

    public void setLookAndFeel() { 
      try {    
	BaseApplicationFrame.log.info("Look and Feel: " + className);

	UIManager.setLookAndFeel(className);
	setCustomProperties();

	//Window[] windows = Window.getWindows();  // 1.6 
	Frame[] windows = Frame.getFrames();
	if (windows != null) { 
	  for (int i = 0; i < windows.length; i++) { 
	    SwingUtilities.updateComponentTreeUI(windows[i]);
	  }
	}
      } catch (Exception e) {
	e.printStackTrace(System.err);
      }
    }

    public void unsetLookAndFeel() {}
    protected void setCustomProperties() {} 

  }

  static class SubstanceLookAndFeel extends LookAndFeel { 

    public SubstanceLookAndFeel() { 
      super("Substance", substanceCreme);
    }

    protected SubstanceLookAndFeel(String displayname, String classname) { 
      super(displayname, classname);
    }

    @Override
    protected void setCustomProperties() {
      //UIManager.put(org.jvnet.substance.SubstanceLookAndFeel.SHOW_EXTRA_WIDGETS, Boolean.TRUE);

    }
  }
}

